# ============================
# Build city boundaries (GPKG)
# ============================

library(terra)

options(stringsAsFactors = FALSE)

# ---- Paths (Windows-friendly, forward slashes) ----
if (!requireNamespace("here", quietly = TRUE)) install.packages("here", quiet = TRUE)
# -------------------------------------------------------------------
# Project base directory (no hardcoded paths)
# -------------------------------------------------------------------
if (!requireNamespace("here", quietly = TRUE)) install.packages("here", quiet = TRUE)
base_dir <- normalizePath(here::here(), winslash = "/")

# -------------------------------------------------------------------
# Define input/output folders
# -------------------------------------------------------------------
in_shapes  <- file.path(base_dir, "Data", "Shape_Files")
in_rasters <- file.path(base_dir, "Data", "Remote_Sensed")
out_dir    <- file.path(base_dir, "Processed_Data", "Boundaries")

dir.create(out_dir, recursive = TRUE, showWarnings = FALSE)


if (!dir.exists(out_dir)) dir.create(out_dir, recursive = TRUE)

# ---- Reference raster (for projection target) ----
ghs_rast <- rast(paste0(in_rasters, "/GHS_BUILT_100m_2020.tif"))

# ---- Helper to load vectors with forward-slash paths ----
vload <- function(rel) {
  p <- rel
  if (!grepl("^C:/", rel)) p <- paste0(in_shapes, "/", rel)
  p <- gsub("\\\\", "/", p)
  if (!file.exists(p)) stop("Shapefile not found: ", p)
  vect(p)
}

# ---- Define city specs: {name, gadm_file, subset_fun} ----
# subset_fun must take a SpatVector 'v' and return the filtered SpatVector
cities <- list(
  
  # ---- SOUTH AFRICA (GADM level 2) ----
  list(name="Johannesburg", gadm="gadm41_ZAF_2.shp",
       subset_fun=function(v) v[v$NAME_2 == "City of Johannesburg", ]),
  list(name="CapeTown", gadm="gadm41_ZAF_2.shp",
       subset_fun=function(v) v[v$NAME_2 == "City of Cape Town", ]),
  list(name="Tshwane", gadm="gadm41_ZAF_2.shp",
       subset_fun=function(v) v[v$NAME_2 == "City of Tshwane", ]),
  list(name="Durban", gadm="gadm41_ZAF_2.shp",
       subset_fun=function(v) v[v$NAME_2 == "eThekwini", ]),
  list(name="Buffalo_City", gadm="gadm41_ZAF_2.shp",
       subset_fun=function(v) v[v$NAME_2 == "Buffalo City", ]),
  list(name="Nelson_Mandela_Bay", gadm="gadm41_ZAF_2.shp",
       subset_fun=function(v) v[v$NAME_2 == "Nelson Mandela Bay", ]),
  
  # ---- NEW YORK CITY (state filter + counties; GADM level 2) ----
  list(name="New_York", gadm="gadm41_USA_2.shp",
       subset_fun=function(v) {
         ny_state <- v[v$NAME_1 == "New York", ]
         ny_state[ny_state$NAME_2 %in% c("New York","Kings","Queens","Bronx","Richmond"), ]
       }),
  
  # ---- KENYA (level 1) ----
  list(name="Nairobi", gadm="gadm41_KEN_1.shp",
       subset_fun=function(v) v[v$NAME_1 == "Nairobi", ]),
  
  # ---- NIGERIA (level 1) ----
  list(name="Lagos", gadm="gadm41_NGA_1.shp",
       subset_fun=function(v) v[v$NAME_1 == "Lagos", ]),
  
  # ---- CÔTE D’IVOIRE (level 1) ----
  list(name="Abidjan", gadm="gadm41_CIV_1.shp",
       subset_fun=function(v) v[v$NAME_1 == "Abidjan", ]),
  
  # ---- EGYPT (level 1) ----
  list(name="Cairo", gadm="gadm41_EGY_1.shp",
       subset_fun=function(v) v[v$NAME_1 == "Al Qahirah", ]),
  
  # ---- UNITED KINGDOM (level 2; by GID_2) ----
  list(name="London", gadm="gadm41_GBR_2.shp",
       subset_fun=function(v) v[v$GID_2 == "GBR.1.36_1", ]),
  
  # ---- TURKIYE (level 1) ----
  list(name="Istanbul", gadm="gadm41_TUR_1.shp",
       subset_fun=function(v) v[v$NAME_1 == "Istanbul", ]),
  
  # ---- KOREA (level 1) ----
  list(name="Seoul", gadm="gadm41_KOR_1.shp",
       subset_fun=function(v) v[v$NAME_1 == "Seoul", ]),
  
  # ---- BRAZIL (level 2; watch encoding of 'São Paulo') ----
  list(name="SaoPaulo", gadm="gadm41_BRA_2.shp",
       subset_fun=function(v) v[enc2utf8(v$NAME_2) == enc2utf8("São Paulo"), ]),
  
  # ---- CHINA (level 2) ----
  list(name="Shenzhen", gadm="gadm41_CHN_2.shp",
       subset_fun=function(v) v[v$NAME_2 == "Shenzhen", ]),
  
  # ---- INDIA (level 2) ----
  list(name="Mumbai", gadm="gadm41_IND_2.shp",
       subset_fun=function(v) v[v$NAME_2 == "Mumbai City", ]),
  
  # ---- MALAYSIA (level 1) ----
  list(name="KualaLumpur", gadm="gadm41_MYS_1.shp",
       subset_fun=function(v) v[v$NAME_1 == "Kuala Lumpur", ]),
  
  # ---- RUSSIA (level 1) ----
  list(name="Moscow", gadm="gadm41_RUS_1.shp",
       subset_fun=function(v) v[v$NAME_1 == "Moscow City", ]),
  
  # ---- MEXICO (level 1) ----
  list(name="Mexico_City", gadm="gadm41_MEX_1.shp",
       subset_fun=function(v) v[v$NAME_1 == "Distrito Federal", ]),
  
  # ---- ARGENTINA (level 1) ----
  list(name="Buenos_Aires", gadm="gadm41_ARG_1.shp",
       subset_fun=function(v) v[v$NAME_1 == "Ciudad de Buenos Aires", ]),
  
  # ---- IRAN (level 1) ----
  list(name="Tehran", gadm="gadm41_IRN_1.shp",
       subset_fun=function(v) v[v$NAME_1 == "Tehran", ]),
  
  # ---- UAE (level 1) ----
  list(name="Dubai", gadm="gadm41_ARE_1.shp",
       subset_fun=function(v) v[v$NAME_1 == "Dubai", ]),
  
  # ---- GERMANY (level 2) ----
  list(name="Frankfurt", gadm="gadm41_DEU_2.shp",
       subset_fun=function(v) v[v$NAME_2 == "Frankfurt am Main", ]),
  
  # ---- SWITZERLAND (level 1; by GID_1) ----
  list(name="Zurich", gadm="gadm41_CHE_1.shp",
       subset_fun=function(v) v[v$GID_1 == "CHE.26_1", ]),
  
  # ---- COLOMBIA (level 1; by GID_1) ----
  list(name="Bogota", gadm="gadm41_COL_1.shp",
       subset_fun=function(v) v[v$GID_1 == "COL.5_2", ])
)

process_city <- function(entry) {
  nm <- entry$name
  message("-> ", nm)
  
  # Load GADM
  gadm <- vload(entry$gadm)
  
  # Subset
  city <- entry$subset_fun(gadm)
  if (nrow(city) == 0) stop("No features after filtering for ", nm)
  
  # Reproject to GHS raster CRS
  city_proj <- project(city, ghs_rast)
  
  # Output file
  gpkg <- paste0(out_dir, "/", nm, ".gpkg")
  
  # Write only the projected version
  writeVector(
    city_proj,
    gpkg,
    layer    = nm,
    filetype = "GPKG",
    overwrite = TRUE
  )
  
  invisible(TRUE)
}


# ---- Run all, continue on errors ----
results <- lapply(cities, function(x) {
  tryCatch({
    process_city(x)
    paste(x$name, "OK")
  }, error = function(e) {
    msg <- paste(x$name, "FAILED:", conditionMessage(e))
    message(msg)
    msg
  })
})

cat("Done.\n")
print(unlist(results))
